package qos.estimator.statistics;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Semaphore;

import qos.estimator.exception.CollectorException;

public class DatabaseStatisticsCollector implements IStatisticsCollector {

 	private Double databaseLocks        = 0d;
	private Double databaseConcSessions = 0d;
	private Double databaseBuffers      = 0d;
	private Semaphore semaphore              = new Semaphore(1);
	private Map<String, Double> dbStatistics = new HashMap<String, Double>( );
	private Connection con                   = null;
	private PreparedStatement psLocks, psSessions, psBuffer = null;
	private ResultSet rs = null;
	
	
	public DatabaseStatisticsCollector( )
	{		
		new Thread(new Runnable(){

			public void run() {
				try {

					while( true ) {
						con = getConnection( );
						psSessions = con.prepareStatement( StringQueries.strQuerySessions );
						rs = psSessions.executeQuery( );
						rs.next( );
						databaseConcSessions = new Double(rs.getInt("numbackends"));
						rs.close( );
						psSessions.close( );

						psLocks = con.prepareStatement( StringQueries.strQueryLocks );
						rs = psLocks.executeQuery( );
						rs.next( );
						databaseLocks = new Double(rs.getInt(1));
						rs.close( );
						psLocks.close( );

						psBuffer = con.prepareStatement( StringQueries.strQueryBuffers );
						rs = psBuffer.executeQuery( );
						rs.next( );
						databaseBuffers = new Double(rs.getInt(1));
						rs.close( );
						psBuffer.close( );
						con.close( );

						dbStatistics.put( "locks", databaseLocks);
						dbStatistics.put( "concSessions", databaseConcSessions);
						dbStatistics.put( "buffers", databaseBuffers);
						try {
							Thread.sleep(5000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
				catch (SQLException e){
					databaseBuffers      = -1d;
					databaseLocks        = -1d;
					databaseConcSessions = -1d;

					e.printStackTrace();
				} finally{
					semaphore.release();
				}
			}

		}).start();
	}
	
	private Connection getConnection() 
	{
		try {
			Class.forName("org.postgresql.Driver");
			Connection conn = DriverManager.getConnection(
					"jdbc:postgresql://localhost:5432/tpch_sf10", "tpch", "tpch");
			return conn;
		} catch (ClassNotFoundException e) 
		{
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public Map<String, Double> next() throws CollectorException 
	{
		try {
			semaphore.acquire();
			if((databaseLocks == -1) || (databaseBuffers == -1 ) || (databaseConcSessions == -1))
			{
				throw new CollectorException("Could not read database statistics. Service started?");
			}
			Map<String, Double> nonVolatileMap = new HashMap<String, Double>(dbStatistics);
			
			nonVolatileMap.put("locks",        new Double(databaseLocks       ));
			nonVolatileMap.put("concSessions", new Double(databaseConcSessions));
			nonVolatileMap.put("buffers"     , new Double(databaseBuffers     ));
			
			return nonVolatileMap;
		} catch (InterruptedException e) 
		{
			throw new CollectorException(e);
		} finally{
			semaphore.release();
		}
	}		
}